package com.sk.bilibili.view.diy;

import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;

import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.MediaItem;
import com.sk.bilibili.R;
import com.sk.bilibili.bean.Danmu;
import com.sk.bilibili.bean.Video;
import com.sk.bilibili.callBack.DanmuCallBack;
import com.sk.bilibili.callBack.OnSeekListener;
import com.sk.bilibili.databinding.ViewPlayerBinding;
import com.sk.bilibili.event.VideoSetEvent;
import com.sk.bilibili.other.BiliBiliDanmuParser;
import com.sk.bilibili.other.BiliBiliDanmuSource;
import com.sk.bilibili.utils.DanmuUtils;
import com.sk.bilibili.utils.TimeUtils;

import org.greenrobot.eventbus.EventBus;

import java.util.List;

import master.flame.danmaku.danmaku.model.BaseDanmaku;
import master.flame.danmaku.danmaku.model.android.DanmakuContext;

public class PlayerView extends ConstraintLayout {

    private ViewPlayerBinding bind;
    private boolean play;
    private DanmakuContext danmakuContext;
    private static final int UPDATE_PROCESS=0;
    private static final int HIDE_CONTROLLER=2;
    private boolean danmu;
    private ExoPlayer player;
    private Handler handler=new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what){
                case UPDATE_PROCESS:updateProcess();break;
                case HIDE_CONTROLLER:bind.clController.setVisibility(GONE);break;
            }
        }
    };

    public void addDanmu(Danmu danmu,boolean user) {
        danmu.setTime((float) bind.dsvShow.getCurrentTime());
        BaseDanmaku danmaku=DanmuUtils.toDanmaku(danmu,danmakuContext,user);
        bind.dsvShow.addDanmaku(danmaku);
    }

    private void updateProcess() {
        handler.sendEmptyMessageDelayed(UPDATE_PROCESS,1000);
        bind.sbShow.setSecondaryProgress((int) player.getBufferedPosition());
        if(!player.isPlaying())return;
        long duration = player.getDuration();
        long current = player.getCurrentPosition();
        bind.sbShow.setMax((int) duration);
        bind.sbShow.setProgress((int) current);
        bind.tvTime.setText(TimeUtils.getProcessTime(current,duration));
    }

    public PlayerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        bind = ViewPlayerBinding.inflate(LayoutInflater.from(context), this, true);
        initData();
        initView();
        bindEvent();
    }

    private void initView() {
        bind.clController.setVisibility(GONE);
        bind.pvShow.setPlayer(player);
        bind.pvShow.setUseController(false);
    }

    private void initData() {
        bind.dsvShow.setCallback((DanmuCallBack) () -> bind.dsvShow.start());
        danmakuContext = DanmakuContext.create();
        bind.dsvShow.enableDanmakuDrawingCache(true);
        danmu=true;
        player = new ExoPlayer.Builder(getContext()).build();
    }

    public void setDanmus(List<Danmu> danmus) {
        BiliBiliDanmuParser parser = new BiliBiliDanmuParser();
        parser.load(new BiliBiliDanmuSource(danmus));
        bind.dsvShow.prepare(parser,danmakuContext);
    }

    private void bindEvent() {
        bind.ivPlayPause.setOnClickListener(v->playOrPause());
        bind.sbShow.setOnSeekBarChangeListener((OnSeekListener) progress -> {
            player.seekTo(progress);
            bind.dsvShow.seekTo((long) progress);
        });
        bind.ivFullscreen.setOnClickListener(v -> EventBus.getDefault().post(VideoSetEvent.fullScreen()));
        bind.ivPlayerBack.setOnClickListener(v -> EventBus.getDefault().post(VideoSetEvent.closeEvent()));
        bind.ivPlayerMore.setOnClickListener(v -> EventBus.getDefault().post(VideoSetEvent.moreEvent()));
        bind.dsvShow.setOnClickListener(v -> {
            bind.clController.setVisibility(VISIBLE);
            handler.removeMessages(HIDE_CONTROLLER);
            handler.sendEmptyMessageDelayed(HIDE_CONTROLLER,7000);
        });
        bind.clController.setOnClickListener(v -> {
            handler.removeMessages(HIDE_CONTROLLER);
            bind.clController.setVisibility(GONE);
        });
        handler.sendEmptyMessageDelayed(UPDATE_PROCESS,1000);
    }

    private void playOrPause() {
        play=!play;
        EventBus.getDefault().post(VideoSetEvent.playEvent(play));
        if(play){
            player.play();
            if(bind.dsvShow.isPrepared())bind.dsvShow.resume();
        }else {
            player.pause();
            if(bind.dsvShow.isPrepared())bind.dsvShow.pause();
        }
        bind.ivPlayPause.setImageResource(play? R.drawable.pause:R.drawable.play);
    }

    public int changeDanmu(){
        danmu=!danmu;
        if(danmu){
            bind.dsvShow.show();
        }else {
            bind.dsvShow.hide();
        }
        return danmu?R.drawable.danmu_open:R.drawable.danmu_close;
    }

    public void play(Video video) {
        player.setMediaItem(MediaItem.fromUri(video.getUrl()));
        bind.tvPlayerTitle.setText(video.getTitle());
        player.prepare();
        player.play();
        bind.dsvShow.seekTo(0L);
        play=true;
        EventBus.getDefault().post(VideoSetEvent.playEvent(play));
    }

    public void start() {
        if(!play)playOrPause();
    }

    public void pause() {
        if(play)playOrPause();
    }

    public void onDestroy() {
        handler.removeMessages(UPDATE_PROCESS);
        bind.dsvShow.stop();
        bind.dsvShow.release();
        player.release();
        player=null;
    }

    public Float getCurrentTime() {
        return player.getCurrentPosition()/1000f;
    }

}